
#include "miscstorage.h"
#include "hlog.h"

namespace zx {

#define ADMIN_NAME_TEXT     "user:admin"
#define ADMIN_PASSWORD_TEXT "password:123"
SINGLETON_IMPL(MiscStorage)

void MiscStorage::open(std::string path) {
    try {
        m_conn.open(path);
        m_conn.execute(R"(  
            CREATE TABLE IF NOT EXISTS kvset (  
                key TEXT NOT NULL UNIQUE,  
                value TEXT NOT NULL  
            );  
        )");

        const char* stmt = "INSERT OR IGNORE INTO kvset (key, value) values (?, ?);";
        char md5_hex[33] = {0};
        hv_md5_hex((unsigned char*)ADMIN_PASSWORD_TEXT, strlen(ADMIN_PASSWORD_TEXT), md5_hex, sizeof(md5_hex));
        m_conn.execute(stmt, ADMIN_NAME_TEXT, (const char*)md5_hex);
    } catch (const std::exception& e) {
        hloge(" open error : %s", e.what());
        throw;
    }
}

void MiscStorage::close(void) {
    m_conn.close();
}

void MiscStorage::kvset(std::string k, std::string v) {
    const char* stmt = R"(
        INSERT OR REPLACE INTO kvset(key, value) VALUES (?, ?);
    )";
    m_conn.execute(stmt, k, v);
}

std::string MiscStorage::kvget(std::string k) {
    const char* stmt = R"(select key, value from kvset where key = ?;)";
    auto r           = m_conn.execute<std::tuple<std::string, std::string>>(stmt, k);

    if (r.empty()) {
        return std::string();
    }
    // for (const auto& [key, value] : r) {
    //     hlogi("key: %s, value: %s", key.c_str(), value.c_str());
    // }
    return std::get<1>(r.at(0));
}

std::unordered_map<std::string, std::string> MiscStorage::kv_keys(std::string k) {
    std::unordered_map<std::string, std::string> ret;
    const char* stmt = R"(select key, value from kvset where key LIKE ?;)";
    auto r           = m_conn.execute<std::tuple<std::string, std::string>>(stmt, k + "%");

    for (const auto& [key, value] : r) {
        // hlogi("key: %s, value: %s", key.c_str(), value.c_str());
        ret[key] = value;
    }

    // for (const auto& [key, value] : ret) {
    //     hlogi("unordered_map key: %s, value: %s", key.c_str(), value.c_str());
    // }
    return ret;
}

void MiscStorage::kvdel(std::string k) {
    const char* stmt = R"(delete from kvset where key = ?;)";
    m_conn.execute(stmt, k);
}

void MiscStorage::kv_del_keys(std::string k) {
    const char* stmt = R"(delete from kvset where key LIKE ?;)";
    m_conn.execute(stmt, k + "%");
}

}  // namespace zx
